home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / rcs5ap1s.lzh / RCSDIFF.C < prev    next >
C/C++ Source or Header  |  1991-01-30  |  12KB  |  414 lines

  1. /*
  2.  *                     RCS rcsdiff operation
  3.  */
  4. /*****************************************************************************
  5.  *                       generate difference between RCS revisions
  6.  *****************************************************************************
  7.  */
  8.  
  9. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  10.    Copyright 1990 by Paul Eggert
  11.    Distributed under license by the Free Software Foundation, Inc.
  12.  
  13. This file is part of RCS.
  14.  
  15. RCS is free software; you can redistribute it and/or modify
  16. it under the terms of the GNU General Public License as published by
  17. the Free Software Foundation; either version 1, or (at your option)
  18. any later version.
  19.  
  20. RCS is distributed in the hope that it will be useful,
  21. but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23. GNU General Public License for more details.
  24.  
  25. You should have received a copy of the GNU General Public License
  26. along with RCS; see the file COPYING.  If not, write to
  27. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  28.  
  29. Report problems and direct all questions to:
  30.  
  31.     rcs-bugs@cs.purdue.edu
  32.  
  33. */
  34.  
  35.  
  36.  
  37.  
  38. /* $Log: rcsdiff.c,v $
  39.  * Revision 5.10  1991/01/30  14:21:32  apratt
  40.  * CI with RCS version 5
  41.  *
  42.  * Revision 5.9  91/01/30  12:02:44  apratt
  43.  * Changed RCS5AKP1 to RCS5AP1
  44.  * 
  45.  * Revision 5.8  91/01/29  17:45:50  apratt
  46.  * Added RCS5AKP1 to usage message, and bugfix: close if can not getfworkstat
  47.  * 
  48.  * Revision 5.7  90/12/13  06:54:07  eggert
  49.  * checked in with -k by apratt at 91.01.10.13.15.08.
  50.  * 
  51.  * Revision 5.7  1990/12/13  06:54:07  eggert
  52.  * GNU diff 1.15 has -u.
  53.  *
  54.  * Revision 5.6  1990/11/01  05:03:39  eggert
  55.  * Remove unneeded setid check.
  56.  *
  57.  * Revision 5.5  1990/10/04  06:30:19  eggert
  58.  * Accumulate exit status across files.
  59.  *
  60.  * Revision 5.4  1990/09/27  01:31:43  eggert
  61.  * Yield 1, not EXIT_FAILURE, when diffs are found.
  62.  *
  63.  * Revision 5.3  1990/09/11  02:41:11  eggert
  64.  * Simplify -kkvl test.
  65.  *
  66.  * Revision 5.2  1990/09/04  17:07:19  eggert
  67.  * Diff's argv was too small by 1.
  68.  *
  69.  * Revision 5.1  1990/08/29  07:13:55  eggert
  70.  * Add -kkvl.
  71.  *
  72.  * Revision 5.0  1990/08/22  08:12:46  eggert
  73.  * Add -k, -V.  Don't use access().  Add setuid support.
  74.  * Remove compile-time limits; use malloc instead.
  75.  * Don't pass arguments with leading '+' to diff; GNU DIFF treats them as options.
  76.  * Add GNU diff's flags.  Make lock and temp files faster and safer.
  77.  * Ansify and Posixate.
  78.  *
  79.  * Revision 4.6  89/05/01  15:12:27  narten
  80.  * changed copyright header to reflect current distribution rules
  81.  * 
  82.  * Revision 4.5  88/08/09  19:12:41  eggert
  83.  * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
  84.  * 
  85.  * Revision 4.4  87/12/18  11:37:46  narten
  86.  * changes Jay Lepreau made in the 4.3 BSD version, to add support for
  87.  * "-i", "-w", and "-t" flags and to permit flags to be bundled together,
  88.  * merged in.
  89.  * 
  90.  * Revision 4.3  87/10/18  10:31:42  narten
  91.  * Updating version numbers. Changes relative to 1.1 actually
  92.  * relative to 4.1
  93.  * 
  94.  * Revision 1.3  87/09/24  13:59:21  narten
  95.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  96.  * warnings)
  97.  * 
  98.  * Revision 1.2  87/03/27  14:22:15  jenkins
  99.  * Port to suns
  100.  * 
  101.  * Revision 4.1  83/05/03  22:13:19  wft
  102.  * Added default branch, option -q, exit status like diff.
  103.  * Added fterror() to replace faterror().
  104.  * 
  105.  * Revision 3.6  83/01/15  17:52:40  wft
  106.  * Expanded mainprogram to handle multiple RCS files.
  107.  *
  108.  * Revision 3.5  83/01/06  09:33:45  wft
  109.  * Fixed passing of -c (context) option to diff.
  110.  *
  111.  * Revision 3.4  82/12/24  15:28:38  wft
  112.  * Added call to catchsig().
  113.  *
  114.  * Revision 3.3  82/12/10  16:08:17  wft
  115.  * Corrected checking of return code from diff; improved error msgs.
  116.  *
  117.  * Revision 3.2  82/12/04  13:20:09  wft
  118.  * replaced getdelta() with gettree(). Changed diagnostics.
  119.  *
  120.  * Revision 3.1  82/11/28  19:25:04  wft
  121.  * Initial revision.
  122.  *
  123.  */
  124. #include "rcsbase.h"
  125.  
  126. #if DIFF_L
  127. static const char *setup_label P((struct buf*,const char*,const char[datesize]));
  128. #endif
  129. static void cleanup P((void));
  130.  
  131. static const char co[] = CO;
  132.  
  133. static int exitstatus;
  134.  
  135. mainProg(rcsdiffId, "rcsdiff", "$Id: rcsdiff.c,v 5.10 1991/01/30 14:21:32 apratt Exp $")
  136. {
  137.     static const char cmdusage[] =
  138.         "\nRCS5AP1 as modified for TOS by Allan Pratt, atari!apratt\nrcsdiff usage: rcsdiff [-q] [-rrev1 [-rrev2]] [-Vn] [diff options] file ...";
  139.     static const char quietarg[] = "-q";
  140.  
  141.     int  revnums;                 /* counter for revision numbers given */
  142.     const char *rev1, *rev2;    /* revision numbers from command line */
  143.     const char *xrev1, *xrev2;    /* expanded revision numbers */
  144.     const char *expandarg, *lexpandarg, *versionarg;
  145. #if DIFF_L
  146.     static struct buf labelbuf[2];
  147.     int file_labels;
  148.     const char **diff_label1, **diff_label2;
  149.     char date2[datesize];
  150. #endif
  151.     const char **diffv, **diffp;    /* argv for subsidiary diff */
  152.     const char **pp, *p, *diffvstr;
  153.     struct buf commarg;
  154.     struct buf numericrev;    /* expanded revision number */
  155.     struct hshentries *gendeltas;    /* deltas to be generated */
  156.     struct hshentry * target;
  157.     int  exit_stats;
  158.     char *argp, *dcp;
  159.     register c;
  160.  
  161.     initid();
  162.     catchints();
  163.  
  164.     bufautobegin(&commarg);
  165.     bufautobegin(&numericrev);
  166.     revnums = 0;
  167.     rev1 = rev2 = xrev2 = nil;
  168. #if DIFF_L
  169.     file_labels = 0;
  170. #endif
  171.     expandarg = versionarg = quietarg; /* i.e. a no-op */
  172.  
  173.     /* Room for args + 2 i/o [+ 2 labels] + 1 file + 1 trailing null.  */
  174.     diffp = diffv = tnalloc(const char*, argc + 4 + 2*DIFF_L);
  175.     *diffp++ = nil;
  176.     *diffp++ = nil;
  177.     *diffp++ = DIFF;
  178.  
  179.     while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
  180.     dcp = argp = *argv + 1;
  181.     while (c = *argp++) switch (c) {
  182.         case 'r':
  183.             if (*argp!='\0') {
  184.             if (revnums==0) {
  185.                 rev1= argp; revnums=1;
  186.             } else if (revnums==1) {
  187.                 rev2= argp; revnums=2;
  188.             } else {
  189.                 faterror("too many revision numbers");
  190.             }
  191.             } /* do nothing for empty -r */
  192.             goto option_handled;
  193. #if DIFF_L
  194.         case 'L':
  195.             if (++file_labels == 2)
  196.             faterror("too many -L options");
  197.             /* fall into */
  198. #endif
  199.         case 'C': case 'D': case 'F': case 'I':
  200.             *dcp++ = c;
  201.             if (*argp)
  202.             do *dcp++ = *argp;
  203.             while (*++argp);
  204.             else {
  205.             if (!--argc)
  206.                 faterror("-%c needs following argument%s",
  207.                     c, cmdusage
  208.                 );
  209.             *diffp++ = *argv++;
  210.             }
  211.             break;
  212.         case 'B': case 'H': case 'T':
  213.         case '0': case '1': case '2': case '3': case '4':
  214.         case '5': case '6': case '7': case '8': case '9':
  215.         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  216.         case 'h': case 'i': case 'n': case 'p':
  217.         case 't': case 'u': case 'w':
  218.             *dcp++ = c;
  219.             break;
  220.         case 'q':
  221.             quietflag=true;
  222.             break;
  223.         case 'V':
  224.             versionarg = *argv;
  225.             setRCSversion(versionarg);
  226.             goto option_handled;
  227.         case 'k':
  228.             expandarg = *argv;
  229.             if (0 <= str2expmode(expandarg+2))
  230.             goto option_handled;
  231.             /* fall into */
  232.         default:
  233.             faterror("unknown option: %s%s", *argv, cmdusage);
  234.         };
  235.       option_handled:
  236.     if (dcp != *argv+1) {
  237.         *dcp = 0;
  238.         *diffp++ = *argv;
  239.     }
  240.     } /* end of option processing */
  241.  
  242.     if (argc<1) faterror("no input file%s", cmdusage);
  243.  
  244.     for (pp = diffv+3, c = 0;  pp<diffp;  )
  245.         c += strlen(*pp++) + 1;
  246.     diffvstr = argp = tnalloc(char, c + 1);
  247.     for (pp = diffv+3;  pp<diffp;  ) {
  248.         p = *pp++;
  249.         *argp++ = ' ';
  250.         while ((*argp = *p++))
  251.             argp++;
  252.     }
  253.     *argp = 0;
  254.  
  255. #if DIFF_L
  256.     diff_label1 = diff_label2 = nil;
  257.     if (file_labels < 2) {
  258.         if (!file_labels)
  259.             diff_label1 = diffp++;
  260.         diff_label2 = diffp++;
  261.     }
  262. #endif
  263.     diffp[2] = nil;
  264.  
  265.     /* now handle all filenames */
  266.     do {
  267.         finptr=NULL;
  268.         ffree();
  269.  
  270.         if (pairfilenames(argc, argv, rcsreadopen, true, false) != 1)
  271.             continue;
  272.         diagnose("==================